<?php
namespace Fyfyu\Admin\Router;

use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\DeleteMapping;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PatchMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\HttpServer\Annotation\PutMapping;
use Hyperf\HttpServer\Annotation\RequestMapping;

use Fyfyu\Admin\Annotations\AdminController;
/**
 * 重写  以使 adminController 生效
 */

class DispatcherFactory extends \Hyperf\HttpServer\Router\DispatcherFactory{
    protected function initAnnotationRoute(array $collector): void
    {
        foreach ($collector as $className => $metadata) {
            if (isset($metadata['_c'][AutoController::class])) {
                if ($this->hasControllerAnnotation($metadata['_c'])) {
                    $message = sprintf('AutoController annotation can\'t use with Controller annotation at the same time in %s.', $className);
                    throw new ConflictAnnotationException($message);
                }
                $middlewares = $this->handleMiddleware($metadata['_c']);
                $this->handleAutoController($className, $metadata['_c'][AutoController::class], $middlewares, $metadata['_m'] ?? []);
            }
            if (isset($metadata['_c'][Controller::class])) {
                $middlewares = $this->handleMiddleware($metadata['_c']);
                $this->handleController($className, $metadata['_c'][Controller::class], $metadata['_m'] ?? [], $middlewares);
            }
            if (isset($metadata['_c'][AdminController::class])) {
                $middlewares = $this->handleMiddleware($metadata['_c']);
                $this->handleAdminController($className,$metadata['_c'][AdminController::class], $metadata['_m'] ?? [], $middlewares);
            }
        }
    }
    protected function getPrefix(string $className, string $prefix): string{
        return ( '/' . ltrim( config( 'admin.prefix' , '') ) ) .parent::getPrefix($className,$prefix);
    }
    protected function handleMiddleware(array $metadata): array{
        $middlewares = parent::handleMiddleware($metadata);
        return array_merge($middlewares,config('admin.middlewares',[]));
    }
    /**
     * copy handleController
     */
    protected function handleAdminController(string $className, AdminController $annotation,array $methodMetadata, array $middlewares = []): void
    {
        if (! $methodMetadata) {
            return;
        }

        $server = $annotation->server ?: config('admin.server') ?: 'http';

        $prefix = $this->getPrefix($className, $annotation->prefix);
        $router = $this->getRouter($server);
        $mappingAnnotations = [
            RequestMapping::class,
            GetMapping::class,
            PostMapping::class,
            PutMapping::class,
            PatchMapping::class,
            DeleteMapping::class,
        ];

        foreach ($methodMetadata as $methodName => $values) {
            $methodMiddlewares = $middlewares;
            // Handle method level middlewares.
            if (isset($values)) {
                $methodMiddlewares = array_merge($methodMiddlewares, $this->handleMiddleware($values));
                $methodMiddlewares = array_unique($methodMiddlewares);
            }

            foreach ($mappingAnnotations as $mappingAnnotation) {
                /** @var Mapping $mapping */
                if ($mapping = $values[$mappingAnnotation] ?? null) {
                    if (! isset($mapping->path) || ! isset($mapping->methods)) {
                        continue;
                    }
                    $path = $mapping->path;

                    if ($path === '') {
                        $path = $prefix;
                    } elseif ($path[0] !== '/') {
                        $path = $prefix . '/' . $path;
                    }

                    $router->addRoute($mapping->methods, $path, [$className, $methodName], [
                        'middleware' => $methodMiddlewares,
                    ]);
                }
            }
        }
    }

}
